/*
 * Copyright (c) 2018 - 2028. www.vtuzx.com Inc. All Rights Reserved
 */
package com.vtuzx.kingdee.xqc_api.service.impl;

import com.mongodb.client.result.UpdateResult;
import com.vtuzx.core.VtuzxException;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.bean.dto.VtuzxPage;
import com.vtuzx.core.bean.dto.VtuzxToken;
import com.vtuzx.core.constant.IVtuzxConst;
import com.vtuzx.core.file.excel.VtuzxExcel;
import com.vtuzx.core.file.excel.VtuzxExcelCell;
import com.vtuzx.core.file.excel.VtuzxExcelRow;
import com.vtuzx.core.file.excel.VtuzxExcelSheet;
import com.vtuzx.core.utils.VtuzxUtil;
import com.vtuzx.fast.service.IFastSettingService;
import com.vtuzx.fast.utils.FastUtil;
import com.vtuzx.kingdee.xqc_api.service.IXqcBasicService;
import com.vtuzx.kingdee.xqc_core.bean.VtuzxArrayList;
import com.vtuzx.kingdee.xqc_core.bean.kingdee.VtuzxKingdeeCloudClient;
import com.vtuzx.kingdee.xqc_core.constant.BillStatus;
import com.vtuzx.kingdee.xqc_core.constant.BillType;
import com.vtuzx.kingdee.xqc_core.constant.ConfigType;
import com.vtuzx.kingdee.xqc_core.constant.IXqcConst;
import com.vtuzx.kingdee.xqc_core.dao.*;
import com.vtuzx.kingdee.xqc_core.service.IVtuzxBasicService;
import com.vtuzx.kingdee.xqc_core.service.IVtuzxKingdeeService;
import com.vtuzx.web.bean.VtuzxDownloadBean;
import com.vtuzx.web.dao.mongo.CustomerDao;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.print.Doc;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 相册服务
 */
@Service
public class XqcBasicServiceImpl implements IXqcBasicService {


    @Autowired
    private IVtuzxKingdeeService kingdeeService;


    /** 物料 */
    @Autowired
    private MaterialDao materialDao;

    /** 仓库 */
    @Autowired
    private StockDao stockDao;

    /** 用户 */
    @Autowired
    private CustomerDao customerDao;

    /** 供应商 */
    @Autowired
    private SupplierDao supplierDao;

    @Autowired
    IFastSettingService settingService;

    /** 仓库 */
    @Autowired
    private StockDetailDao stockDetailDao;

    /** 账号信息 */
    @Autowired
    private StoreTokenDao storeTokenDao;

    /** 仓库 */
    @Autowired
    private DepartmentDao departmentDao;

    /** 账号信息 */
    @Autowired
    private EmpInfoDao empInfoDao;

    /** 托盘信息 */
    @Autowired
    private TrayDao trayDao;

    /** bom信息 */
    @Autowired
    private BomDao bomDao;

    @Autowired
    private IVtuzxBasicService basicService;

    @Autowired
    private TraceabilityCodeDao traceabilityCodeDao;

    @Autowired
    private TraceabilityCodeDetailDao traceabilityCodeDetailDao;

    @Override
    public void deleteMaterial(VtuzxToken token, List<String> ids) {
        materialDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(FastUtil.convertId(ids)));
    }

    @Override
    public VtuzxMap getMaterial(VtuzxToken token, String key, int pageSize) {
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(key)) {
            cond.orOperator(Criteria.where("fNumber").regex("^" + key + ".*$"), Criteria.where("fName").regex("^.*" + key + ".*$"));
        }
        VtuzxPage page = materialDao.page(cond, new Document("fNumber", 1), 0, 0);
        List<VtuzxMap> dataList = page.iterator(doc ->
                new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber"))
                .append("fSpecification", VtuzxUtil.getString(doc, "fSpecification")));

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getMaterial(VtuzxToken token, Map<String, Object> param) {
        String fName = VtuzxUtil.getString(param, "fName");
        String fNumber = VtuzxUtil.getString(param, "fNumber");
        String fMATERIALID = VtuzxUtil.getString(param, "fMATERIALID");
        String fCreateOrgName = VtuzxUtil.getString(param, "fCreateOrgName");
        String fMaterialGroupName = VtuzxUtil.getString(param, "fMaterialGroupName");
        String fTaxRateName = VtuzxUtil.getString(param, "fTaxRateName");
        String fSpecification = VtuzxUtil.getString(param, "fSpecification");
        String goodsType = VtuzxUtil.getString(param, "goodsType");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(fName)) {
            cond.and("fName").regex(fName);
        }
        if (!VtuzxUtil.isEmpty(fNumber)) {
            cond.and("fNumber").regex("^" + fNumber + ".*$");
        }
        if (!VtuzxUtil.isEmpty(fMATERIALID)) {
            cond.and("fMATERIALID").regex(fMATERIALID);
        }
        if (!VtuzxUtil.isEmpty(fCreateOrgName)) {
            cond.and("fCreateOrgName").regex(fCreateOrgName);
        }
        if (!VtuzxUtil.isEmpty(goodsType)) {
            cond.and("goodsType").regex(goodsType);
        }
        if (!VtuzxUtil.isEmpty(fMaterialGroupName)) {
            cond.and("fMaterialGroupName").regex(fMaterialGroupName);
        }
        if (!VtuzxUtil.isEmpty(fTaxRateName)) {
            cond.and("fTaxRateName").regex(fTaxRateName);
        }
        if (!VtuzxUtil.isEmpty(fSpecification)) {
            cond.and("fSpecification").regex(fSpecification);
        }

        VtuzxPage page = materialDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fMATERIALID", VtuzxUtil.getString(doc, "fMATERIALID"))
                .append("fCreateOrgNumber", VtuzxUtil.getString(doc, "fCreateOrgNumber"))
                .append("fCreateOrgName", VtuzxUtil.getString(doc, "fCreateOrgName"))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber"))
                .append("fSpecification", VtuzxUtil.getString(doc, "fSpecification"))
                .append("fMaterialGroupNumber", VtuzxUtil.getString(doc, "fMaterialGroupNumber"))
                .append("fMaterialGroupName", VtuzxUtil.getString(doc, "fMaterialGroupName"))
                .append("fTaxRateNumber", VtuzxUtil.getString(doc, "fTaxRateNumber"))
                .append("fTaxRateName", VtuzxUtil.getString(doc, "fTaxRateName"))
                .append("fDocumentStatus", VtuzxUtil.getString(doc, "fDocumentStatus"))
                .append("fErpClsID", VtuzxUtil.getString(doc, "fErpClsID"))
                .append("fBaseUnitIdFName", VtuzxUtil.getString(doc, "fBaseUnitIdFName"))
                .append("fBaseUnitIdNumber", VtuzxUtil.getString(doc, "fBaseUnitIdNumber"))
                .append("prdStandardNo", VtuzxUtil.getString(doc, "prdStandardNo"))
                .append("prdLicence", VtuzxUtil.getString(doc, "prdLicence"))
                .append("goodsType", VtuzxUtil.getString(doc, "goodsType"))
                .append("seaAreaLocation", VtuzxUtil.getString(doc, "seaAreaLocation"))
                .append("fCreateDate", VtuzxUtil.getString(doc, "fCreateDate").substring(0, 10)));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }


    @Async
    @Override
    public void syncMaterial(VtuzxToken token, Map<String, Object> p) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        ObjectId _storeId = VtuzxUtil.getObject(storeToken, IVtuzxConst.Key__id);
        storeTokenDao.updateById(_storeId, new Document("reloadMaterial", true).append("reloadMaterialStartTime", new Date()).append("reloadMaterialRes", true).append("reloadMaterialMsg", ""));
        try {
            basicService.syncMaterial();
            storeTokenDao.updateById(_storeId, new Document("reloadMaterial", false).append("reloadMaterialEndTime", new Date()).append("lastReloadMaterialTime",new Date()));
        } catch(Exception e) {
            storeTokenDao.updateById(_storeId, new Document("reloadMaterial", false).append("reloadMaterialEndTime", new Date()).append("reloadMaterialRes", false).append("reloadMaterialMsg", e.getMessage()));
        }
    }

    /**
     * 获取同步物料处理结果
     */
    public VtuzxMap getMaterialReloadResult(VtuzxToken token, Map<String, Object> p) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        return new VtuzxMap("reloadMaterial", VtuzxUtil.getBoolean(storeToken, "reloadMaterial"))
                .append("reloadMaterialRes", VtuzxUtil.getBoolean(storeToken, "reloadMaterialRes"))
                .append("reloadMaterialMsg", VtuzxUtil.getString(storeToken, "reloadMaterialMsg"))
                .append("reloadMaterialStartTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadMaterialStartTime")))
                .append("reloadMaterialEndTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadMaterialEndTime")));
    }



    @Override
    public void deleteStock(VtuzxToken token, List<String> ids) {
        stockDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(FastUtil.convertId(ids)));
    }

    @Override
    public VtuzxMap getStock(VtuzxToken token, Map<String, Object> param) {
        String fName = VtuzxUtil.getString(param, "fName");
        String fNumber = VtuzxUtil.getString(param, "fNumber");
        String fStockId = VtuzxUtil.getString(param, "fStockId");
        String fCreateOrgName = VtuzxUtil.getString(param, "fCreateOrgName");
        String fOraCKYTSX = VtuzxUtil.getString(param, "fOraCKYTSX");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(fName)) {
            cond.and("fName").regex(fName);
        }
        if (!VtuzxUtil.isEmpty(fNumber)) {
            cond.and("fNumber").regex(fNumber);
        }
        if (!VtuzxUtil.isEmpty(fStockId)) {
            cond.and("fStockId").regex(fStockId);
        }
        if (!VtuzxUtil.isEmpty(fCreateOrgName)) {
            cond.and("fCreateOrgName").regex(fCreateOrgName);
        }
        if (!VtuzxUtil.isEmpty(fOraCKYTSX)) {
            cond.and("fOraCKYTSX").regex(fOraCKYTSX);
        }

        VtuzxPage page = stockDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fStockId", VtuzxUtil.getString(doc, "fStockId"))
                .append("fCreateOrgNumber", VtuzxUtil.getString(doc, "fCreateOrgNumber"))
                .append("fCreateOrgName", VtuzxUtil.getString(doc, "fCreateOrgName"))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber"))
                .append("fStockProperty", VtuzxUtil.getString(doc, "fStockProperty"))
                .append("fDocumentStatus", VtuzxUtil.getString(doc, "fDocumentStatus"))
                .append("fAddress", VtuzxUtil.getString(doc, "fAddress"))
                .append("fAllowMinusQty", VtuzxUtil.getBoolean(doc, "fAllowMinusQty"))
                .append("fPrincipal", VtuzxUtil.getString(doc, "fPrincipal"))
                .append("fOraCKYTSX", VtuzxUtil.getString(doc, "fOraCKYTSX"))
                .append("fCreateDate", VtuzxUtil.getString(doc, "fCreateDate").substring(0, 10)));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Async
    @Override
    public void syncStock(VtuzxToken token, Map<String, Object> p) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        ObjectId _storeId = VtuzxUtil.getObject(storeToken, IVtuzxConst.Key__id);
        storeTokenDao.updateById(_storeId, new Document("reloadStock", true).append("reloadStockStartTime", new Date()).append("reloadStockRes", true).append("reloadStockMsg", ""));
        try {
            basicService.syncStock();
            storeTokenDao.updateById(_storeId, new Document("reloadStock", false).append("reloadStockEndTime", new Date()));
        } catch(Exception e) {
            storeTokenDao.updateById(_storeId, new Document("reloadStock", false).append("reloadStockEndTime", new Date()).append("reloadStockRes", false).append("reloadStockMsg", e.getMessage()));
        }
    }

    /**
     * 获取同步仓库处理结果
     */
    public VtuzxMap getStockReloadResult(VtuzxToken token, Map<String, Object> p) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        return new VtuzxMap("reloadStock", VtuzxUtil.getBoolean(storeToken, "reloadStock"))
                .append("reloadStockRes", VtuzxUtil.getBoolean(storeToken, "reloadStockRes"))
                .append("reloadStockMsg", VtuzxUtil.getString(storeToken, "reloadStockMsg"))
                .append("reloadStockStartTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadStockStartTime")))
                .append("reloadStockEndTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadStockEndTime")));
    }

    @Override
    public void deleteSupplier(VtuzxToken token, String fNumber) {
        supplierDao.updateManyRedirect(Criteria.where("fNumber").is(fNumber),
                new Document("$set",new Document("isDelete",true)));
        //supplierDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(FastUtil.convertId(ids)));
    }

    @Override
    public VtuzxMap getSupplierByKey(VtuzxToken token, String key, int pageSize, int pageIndex) {
        Criteria cond = new Criteria();
        //供应商做了逻辑删除，查询没有被删除的
        cond.and("isDelete").ne(true);
        if (!VtuzxUtil.isEmpty(key)) {
            cond.orOperator(Criteria.where("fNumber").regex("^" + key + ".*$"), Criteria.where("fName").regex("^.*" + key + ".*$"));
        }
        VtuzxPage page = supplierDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc ->
                new VtuzxMap("fName", VtuzxUtil.getString(doc, "fName"))
                        .append("fNumber", VtuzxUtil.getString(doc, "fNumber")));

        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append(IVtuzxConst.Key_total, page.total());
    }

    @Override
    public VtuzxMap getSupplier(VtuzxToken token, Map<String, Object> param) {
        String fSupplierId = VtuzxUtil.getString(param, "fSupplierId");
        String fName = VtuzxUtil.getString(param, "fName");
        String fNumber = VtuzxUtil.getString(param, "fNumber");
        String fGroupFName = VtuzxUtil.getString(param, "fGroupFName");
        String fCreateOrgName = VtuzxUtil.getString(param, "fCreateOrgName");
        String f_ora_pch = VtuzxUtil.getString(param, "f_ora_pch");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
//        cond.and("isDelete").ne(true);
        if (!VtuzxUtil.isEmpty(fSupplierId)) {
            cond.and("fSupplierId").regex(fSupplierId);
        }
        if (!VtuzxUtil.isEmpty(fName)) {
            cond.and("fName").regex(fName);
        }
        if (!VtuzxUtil.isEmpty(fNumber)) {
            cond.and("fNumber").regex("^" + fNumber + ".*$");
        }
        if (!VtuzxUtil.isEmpty(fGroupFName)) {
            cond.and("fGroupFName").regex(fGroupFName);
        }
        if (!VtuzxUtil.isEmpty(fCreateOrgName)) {
            cond.and("fCreateOrgName").regex(fCreateOrgName);
        }
        if (!VtuzxUtil.isEmpty(f_ora_pch)) {
            cond.and("f_ora_pch").is(f_ora_pch);
        }

        VtuzxPage page = supplierDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fSupplierId", VtuzxUtil.getString(doc, "fSupplierId"))
                .append("f_ora_pch", VtuzxUtil.getString(doc, "f_ora_pch"))
                .append("fCreateOrgNumber", VtuzxUtil.getString(doc, "fCreateOrgNumber"))
                .append("fCreateOrgName", VtuzxUtil.getString(doc, "fCreateOrgName"))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber"))
                .append("fForbidStatus", VtuzxUtil.getString(doc, "fForbidStatus"))
                .append("fGroupFName", VtuzxUtil.getString(doc, "fGroupFName"))
                .append("fGroupFNumber", VtuzxUtil.getString(doc, "fGroupFNumber"))
                .append("seaAreaPosition", VtuzxUtil.getString(doc, "seaAreaPosition"))
                .append("seaAreaPositionStr", VtuzxUtil.getString(doc, "seaAreaPositionStr"))
                .append("fDocumentStatus", VtuzxUtil.getBoolean(doc, "fDocumentStatus"))
                .append("isDelete", VtuzxUtil.getString(doc, "isDelete"))
                .append("fCreateDate", VtuzxUtil.getString(doc, "fCreateDate").substring(0, 10)));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }


    @Async
    @Override
    public void syncSupplier(VtuzxToken token, Map<String, Object> p) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        ObjectId _storeId = VtuzxUtil.getObject(storeToken, IVtuzxConst.Key__id);
        storeTokenDao.updateById(_storeId, new Document("reloadSupplier", true).append("reloadSupplierStartTime", new Date()).append("reloadSupplierRes", true).append("reloadSupplierMsg", ""));
        try {
            basicService.syncSupplier();
            storeTokenDao.updateById(_storeId, new Document("reloadSupplier", false).append("reloadSupplierEndTime", new Date()));
        } catch(Exception e) {
            storeTokenDao.updateById(_storeId, new Document("reloadSupplier", false).append("reloadSupplierEndTime", new Date()).append("reloadSupplierRes", false).append("reloadSupplierMsg", e.getMessage()));
        }
    }

    /**
     * 获取同步供应商处理结果
     */
    public VtuzxMap getSupplierReloadResult(VtuzxToken token, Map<String, Object> p) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        return new VtuzxMap("reloadSupplier", VtuzxUtil.getBoolean(storeToken, "reloadSupplier"))
                .append("reloadSupplierRes", VtuzxUtil.getBoolean(storeToken, "reloadSupplierRes"))
                .append("reloadSupplierMsg", VtuzxUtil.getString(storeToken, "reloadSupplierMsg"))
                .append("reloadSupplierStartTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadSupplierStartTime")))
                .append("reloadSupplierEndTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadSupplierEndTime")));
    }

    @Override
    public VtuzxMap getStockLocations(String stockNo) {
        return null;
    }

    @Override
    public VtuzxMap getStockLocation(String stockNo, String locationNo) throws VtuzxException {
        Document location = stockDetailDao.findOne(Criteria.where("fNumber").is(stockNo).and("locationNo").is(locationNo));
        if (location == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        return new VtuzxMap("locationNo", VtuzxUtil.getString(location, "locationNo"))
                .append("locationName", VtuzxUtil.getString(location, "locationName"))
                .append("position", VtuzxUtil.getString(location, "position"))
                .append("stockNo", VtuzxUtil.getString(location, "fNumber"))
                .append("stockName", VtuzxUtil.getString(location, "fName"))
                .append("remark", VtuzxUtil.getString(location, "remark"));
    }

    @Override
    public VtuzxMap getStockDetail(String fNumber) throws VtuzxException {
        Document doc = stockDao.findOne(Criteria.where("fNumber").is(fNumber));
        if (doc == null) {
            throw new VtuzxException(IVtuzxConst.Msg_E_target_not_exist);
        }
        Document header = new Document();
        header.append("fName", VtuzxUtil.getObject(doc, "fName"));
        header.append("fNumber", VtuzxUtil.getObject(doc, "fNumber"));
        header.append("fCreateOrgName", VtuzxUtil.getObject(doc, "fCreateOrgName"));
        header.append("fCreateOrgNumber", VtuzxUtil.getObject(doc, "fCreateOrgNumber"));
        header.append("fForbidStatus", VtuzxUtil.getObject(doc, "fForbidStatus"));
        header.append("fCreateDate", VtuzxUtil.getObject(doc, "fCreateDate"));
        header.append("fCreateDate", VtuzxUtil.getString(doc, "fCreateDate").substring(0, 10));
        header.append("fAddress", VtuzxUtil.getObject(doc, "fAddress"));
        header.append("fOraCKYTSX", VtuzxUtil.getObject(doc, "fOraCKYTSX"));
        header.append("fAllowMinusQty", VtuzxUtil.getObject(doc, "fAllowMinusQty"));
        header.append("ip", VtuzxUtil.getObject(doc, "ip"));
        Iterator<Document> locationItr = stockDetailDao.findList(Criteria.where("fNumber").is(fNumber), null, 0, 0);
        List<VtuzxMap> locationList = new ArrayList<>();
        while(locationItr.hasNext()) {
            Document locationDoc = locationItr.next();
            locationList.add(new VtuzxMap("locationNo", VtuzxUtil.getObject(locationDoc, "locationNo"))
                    .append("locationName", VtuzxUtil.getObject(locationDoc, "locationName"))
                    .append("remark", VtuzxUtil.getObject(locationDoc, "remark"))
                    .append("position", VtuzxUtil.getObject(locationDoc, "position"))
                    .append("rfid", VtuzxUtil.getObject(locationDoc, "rfid")));
        }
        return new VtuzxMap("header", header).append("locationList", locationList);

    }

    @Override
    public VtuzxMap saveStockDetail(Map<String, Object> param) throws VtuzxException {
        // 获取用户信息
        String fName = VtuzxUtil.getString(param, "fName");
        String fNumber = VtuzxUtil.getString(param, "fNumber");
        List<String> ipList = VtuzxUtil.getObject(param, "ipList");
        stockDao.updateOne(Criteria.where("fNumber").is(fNumber), new Document("ip", ipList));
        List<Map<String, Object>> locationList = VtuzxUtil.getObject(param, "locationList");
        List<Document> detailList = new ArrayList<>();
        Iterator<Document> detailItr = stockDetailDao.findList(Criteria.where("fNumber").is(fNumber), null, 0, 0);
        while(detailItr.hasNext()) {
            detailList.add(detailItr.next());
        }
        if (detailList.size() == 0) {
            for (Map<String, Object> location: locationList) {
                Document doc = new Document(location);
                stockDetailDao.insertOne(doc.append("fName", fName).append("fNumber", fNumber));
            }
        } else {
            List<ObjectId> _delIds = new ArrayList<>();
            List<Document> insertList = new ArrayList<>();
            for (Map<String, Object> location: locationList) {
                Document doc = new Document(location);
                boolean exist = false;
                String stockName = VtuzxUtil.getString(doc, "locationName");
                for (Document data: detailList) {
                    ObjectId id = VtuzxUtil.getObject(data, IVtuzxConst.Key__id);
                    String locationName = VtuzxUtil.getString(data, "locationName");
                    if (locationName.equals(stockName)) {
                        stockDetailDao.updateById(id, doc);
                        exist = true;
                        detailList.remove(data);
                        break;
                    }
                }
                if (!exist) {
                    insertList.add(doc.append("fName", fName).append("fNumber", fNumber));
                }
            }
            for(Document detail: detailList) {
                _delIds.add(VtuzxUtil.getObject(detail, IVtuzxConst.Key__id));
            }
            if (_delIds.size() > 0) {
                stockDetailDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(_delIds));
            }
            if (insertList.size() > 0) {
                stockDetailDao.insertMany(insertList);
            }
        }
        return new VtuzxMap("fName", fName);
    }



    @Override
    public VtuzxMap getCustomerStock(ObjectId userId) {
        List<VtuzxMap> stockList = new ArrayList<>();
        Document customerDoc = customerDao.findById(userId);
        List<String> stockNos = VtuzxUtil.getObject(customerDoc, "stockNos");
        for (String stock: stockNos) {
            VtuzxMap stocks = new VtuzxMap();
            Document stockDoc = stockDao.findOne(Criteria.where("fNumber").is(stock));
            String stockName = VtuzxUtil.getString(stockDoc, "fName");
            stocks.append("stockNo", stock).append("stockName", stockName);
            stockList.add(stocks);
        }

        return new VtuzxMap("stockList", stockList);
    }

    @Override
    public VtuzxMap stockToGetLocation(String stockNo) {
        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> locationItr = stockDetailDao.findList(Criteria.where("fNumber").is(stockNo), new Document("createTime", -1), 0, 0);
        while (locationItr.hasNext()) {
            Document locationDoc = locationItr.next();
            VtuzxMap locationMap = new VtuzxMap(locationDoc);
            dataList.add(locationMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void getDepartment(VtuzxToken token, Map<String, Object> param) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        List<VtuzxMap> deptList = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FCreateOrgId.FName", //创建组织
                        "FCreateOrgId.FNumber", //创建组织
                        "FName",
                        "FNumber",
                        "FDocumentStatus",
                        "FForbidStatus",
                        "FGroup.FNumber",
                        "FDEPTID"
                ),
                null, "FDEPTID", 0, 0);
        for (VtuzxMap dept: deptList) {
            String fDeptId = VtuzxUtil.getString(dept, "FDEPTID");
            String fCreateOrgNumber = VtuzxUtil.getString(dept, "FCreateOrgId.FNumber");
            String fCreateOrgName = VtuzxUtil.getString(dept, "FCreateOrgId.FName");
            String fName = VtuzxUtil.getString(dept, "FName");
            String fNumber = VtuzxUtil.getString(dept, "FNumber");
            String fDocumentStatus = VtuzxUtil.getString(dept, "FDocumentStatus");
            String fForbidStatus = VtuzxUtil.getString(dept, "FForbidStatus");
            String fGroup = VtuzxUtil.getString(dept, "FGroup.FNumber");
            Document data = new Document("fDeptId", fDeptId)
                    .append("fCreateOrgNumber", fCreateOrgNumber)
                    .append("fCreateOrgName", fCreateOrgName)
                    .append("fForbidStatus", fForbidStatus)
                    .append("fName", fName)
                    .append("fNumber", fNumber)
                    .append("fDocumentStatus", fDocumentStatus)
                    .append("fGroup", fGroup);

            Document deptDoc = departmentDao.findOne(Criteria.where("fDeptId").is(fDeptId));
            if (VtuzxUtil.isEmpty(deptDoc)) {
                departmentDao.insertOne(data);
            } else {
                ObjectId id = VtuzxUtil.getObject(deptDoc, IVtuzxConst.Key__id);
                data.remove("fDeptId");
                departmentDao.updateById(id, data);
            }
        }
    }

    @Override
    public VtuzxMap getDepartmentList(VtuzxToken token, Map<String, Object> param) {
        String key = VtuzxUtil.getString(param, "key");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        String group = VtuzxUtil.getString(param, "group");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(key)) {
            cond.orOperator(Criteria.where("fNumber").regex("^" + key + ".*$"), Criteria.where("fName").regex("^.*" + key + ".*$"));
        }
        if (!VtuzxUtil.isEmpty(group)) {
            cond.and("fGroup").is(group);
        }
        VtuzxPage page = departmentDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fDeptId", VtuzxUtil.getString(doc, "fDeptId"))
                .append("fCreateOrgNumber", VtuzxUtil.getString(doc, "fCreateOrgNumber"))
                .append("fCreateOrgName", VtuzxUtil.getString(doc, "fCreateOrgName"))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fGroup", VtuzxUtil.getString(doc, "fGroup"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void getEmpInfo(VtuzxToken token, Map<String, Object> param) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        List<VtuzxMap> empInfoList = kingdeeService.query(client, "BD_Empinfo", new VtuzxArrayList<>(
                        "FCreateOrgId.FName", //创建组织
                        "FCreateOrgId.FNumber", //创建组织
                        "FName",
                        "FNumber",
                        "FDocumentStatus",
                        "FForbidStatus",
                        "FPostDept",
                        "FID"
                ),
                null, "FID", 0, 0);
        for (VtuzxMap empInfo: empInfoList) {
            String fID = VtuzxUtil.getString(empInfo, "FID");
            String fCreateOrgNumber = VtuzxUtil.getString(empInfo, "FCreateOrgId.FNumber");
            String fCreateOrgName = VtuzxUtil.getString(empInfo, "FCreateOrgId.FName");
            String fName = VtuzxUtil.getString(empInfo, "FName");
            String fNumber = VtuzxUtil.getString(empInfo, "FNumber");
            String fDocumentStatus = VtuzxUtil.getString(empInfo, "FDocumentStatus");
            String fForbidStatus = VtuzxUtil.getString(empInfo, "FForbidStatus");
            String fPostEntity_FPostDept = VtuzxUtil.getString(empInfo, "FPostDept");
            Document data = new Document("fID", fID)
                    .append("fCreateOrgNumber", fCreateOrgNumber)
                    .append("fCreateOrgName", fCreateOrgName)
                    .append("fForbidStatus", fForbidStatus)
                    .append("fName", fName)
                    .append("fNumber", fNumber)
                    .append("fDocumentStatus", fDocumentStatus)
                    .append("fPostEntity_FPostDept", fPostEntity_FPostDept);

            Document empInfoDoc = empInfoDao.findOne(Criteria.where("fID").is(fID));
            if (VtuzxUtil.isEmpty(empInfoDoc)) {
                empInfoDao.insertOne(data);
            } else {
                ObjectId id = VtuzxUtil.getObject(empInfoDoc, IVtuzxConst.Key__id);
                data.remove("fID");
                empInfoDao.updateById(id, data);
            }
        }
    }

    @Override
    public void addTray(VtuzxToken token, Map<String, Object> param) throws VtuzxException {
        String trayNumber = VtuzxUtil.getString(param, "trayNumber");
        if (!trayNumber.startsWith("T")) {
            throw new VtuzxException("托盘编码请以T开头");
        }
        if (trayNumber.length() != 8) {
            throw new VtuzxException("托盘编码长度为8位");
        }
        ObjectId userId = VtuzxUtil.getObject(token, "_id");
        String name = VtuzxUtil.getString(token, "name");
        String trayName = VtuzxUtil.getString(param, "trayName");
        String remark = VtuzxUtil.getString(param, "remark");
        Document doc = new Document("trayNumber", trayNumber)
                .append("remark", remark)
                .append("trayName", trayName)
                .append("createUserId", userId)
                .append("createUserName", name);

        Document trayDoc = trayDao.findOne(Criteria.where("trayNumber").is(trayNumber));
        if (!VtuzxUtil.isEmpty(trayDoc)) {
            throw new VtuzxException("托盘编码不能重复");
        }

        trayDao.insertOne(doc);
    }

    @Override
    public VtuzxMap getTrayList(VtuzxToken token, Map<String, Object> param) {
        String trayNumber = VtuzxUtil.getString(param, "trayNumber");
        String trayName = VtuzxUtil.getString(param, "trayName");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(trayNumber)) {
            cond.and("trayNumber").regex(trayNumber);
        }
        if (!VtuzxUtil.isEmpty(trayName)) {
            cond.and("trayName").regex(trayName);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            cond.and("createUserName").regex(createUserName);
        }

        VtuzxPage page = trayDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("trayNumber", VtuzxUtil.getString(doc, "trayNumber"))
                .append("rfid", VtuzxUtil.getObject(doc, "rfid"))
                .append("remark", VtuzxUtil.getString(doc, "remark"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("highlight",VtuzxUtil.getString(doc,"highlight"))
                .append("trayName", VtuzxUtil.getString(doc, "trayName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void updateTray(VtuzxToken token, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        String trayNumber = VtuzxUtil.getString(param, "trayNumber");
        String remark = VtuzxUtil.getString(param, "remark");
        Document doc = new Document("trayNumber", trayNumber)
                .append("remark", remark);

        trayDao.updateById(id, doc);
    }

    @Override
    public void deleteTray(VtuzxToken token, Map<String, Object> param) {
        List<String> ids = VtuzxUtil.getObject(param, "ids");
        for (String id: ids) {
            trayDao.deleteById(id);
        }
    }

    @Override
    public void deleteBom(VtuzxToken token, List<String> ids) {
        bomDao.deleteMany(Criteria.where(IVtuzxConst.Key__id).in(FastUtil.convertId(ids)));
    }

    @Override
    public VtuzxMap getBom(VtuzxToken token, String key, int pageSize, int pageIndex) {
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(key)) {
            cond.orOperator(Criteria.where("materialNo").regex("^" + key + ".*$", "i"), Criteria.where("materialName").regex("^.*" + key + ".*$", "i"));
        }
        List<Document> dataList = new ArrayList<>();
        Iterator<Document> itr = bomDao.getList(cond,new Document("order",-1), pageIndex, pageSize);
        while(itr.hasNext()) {
            Document bomDoc = itr.next();
            dataList.add(bomDoc);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getBom(VtuzxToken token, Map<String, Object> param) {
        String fName = VtuzxUtil.getString(param, "fName");
        String fNumber = VtuzxUtil.getString(param, "fNumber");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(fName)) {
            cond.and("fName").regex(fName);
        }
        if (!VtuzxUtil.isEmpty(fNumber)) {
            cond.and("fNumber").regex(fNumber);
        }
        VtuzxPage page = bomDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fId", VtuzxUtil.getString(doc, "fId"))
                .append("fCreateOrgNumber", VtuzxUtil.getString(doc, "fCreateOrgNumber"))
                .append("fCreateOrgName", VtuzxUtil.getString(doc, "fCreateOrgName"))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber"))
                .append("materialNo", VtuzxUtil.getString(doc, "materialNo"))
                .append("materialName", VtuzxUtil.getString(doc, "materialName"))
                .append("materialModel", VtuzxUtil.getString(doc, "materialModel"))
                .append("unitNumber", VtuzxUtil.getString(doc, "unitNumber"))
                .append("unitName", VtuzxUtil.getString(doc, "unitName"))
                .append("materialProperty", VtuzxUtil.getString(doc, "materialProperty"))
                .append("childList", VtuzxUtil.getObject(doc, "childList")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void syncBom(VtuzxToken token, Map<String, Object> param) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        ObjectId _storeId = VtuzxUtil.getObject(storeToken, IVtuzxConst.Key__id);
        storeTokenDao.updateById(_storeId, new Document("reloadBom", true).append("reloadBomStartTime", new Date()).append("reloadBomRes", true).append("reloadBomMsg", ""));
        try {
            basicService.syncBom();
            storeTokenDao.updateById(_storeId, new Document("reloadBom", false).append("reloadBomEndTime", new Date()).append("lastReloadBomTime",new Date()));
        } catch(Exception e) {
            storeTokenDao.updateById(_storeId, new Document("reloadBom", false).append("reloadBomEndTime", new Date()).append("reloadBomRes", false).append("reloadBomMsg", e.getMessage()));
        }
    }

    @Override
    public VtuzxMap getBomReloadResult(VtuzxToken token, Map<String, Object> param) {
        Document storeToken = storeTokenDao.findOne(Criteria.where("type").is(ConfigType.Kingdee.toString()));
        return new VtuzxMap("reloadBom", VtuzxUtil.getBoolean(storeToken, "reloadBom"))
                .append("reloadBomRes", VtuzxUtil.getBoolean(storeToken, "reloadBomRes"))
                .append("reloadBomMsg", VtuzxUtil.getString(storeToken, "reloadBomMsg"))
                .append("reloadBomStartTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadBomStartTime")))
                .append("reloadBomEndTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(storeToken, "reloadBomEndTime")));
    }

    @Override
    public void updateSupplier(VtuzxToken token, Map<String, Object> param) {
        String id = VtuzxUtil.getString(param, "id");
        String seaAreaPosition = VtuzxUtil.getString(param, "seaAreaPosition");
        String seaAreaPositionStr = VtuzxUtil.getString(param, "seaAreaPositionStr");
        supplierDao.updateById(id, new Document("seaAreaPosition", seaAreaPosition).append("seaAreaPositionStr", seaAreaPositionStr));
    }

    @Override
    public void createTraceabilityCode(VtuzxToken token, Map<String, Object> param) throws InterruptedException, VtuzxException {
        VtuzxMap sysParamMap = settingService.getParameters(new VtuzxMap("keys", new VtuzxArrayList<>("traceabilityCodeUrl")));
        VtuzxMap traceabilityCodeUrlMap = VtuzxUtil.getObject(sysParamMap, "traceabilityCodeUrl");
        if (traceabilityCodeUrlMap == null) {
            throw new VtuzxException(IXqcConst.Msg_E_system);
        }
        String value = VtuzxUtil.getString(traceabilityCodeUrlMap, "value");
        String billNo = IXqcConst.createBillNo(BillType.ZSM);
        ObjectId userId = VtuzxUtil.getObject(token, IVtuzxConst.Key__id);
        String userName = VtuzxUtil.getString(token, "name");
        List<Document> traceabilityCodeList = new ArrayList<>();
        int codeCount = VtuzxUtil.getInt(param, "codeCount");

        Document document = new Document("codeCount", codeCount)
                .append("enabledCount", 0)
                .append("noEnabledCount", codeCount)
                .append("createUserId", userId)
                .append("createUserName", userName)
                .append("billNo", billNo);

        ObjectId traceabilityCodeId = traceabilityCodeDao.insertOne(document);

        for (int i = 0; i < codeCount; i++) {
            String traceabilityCode = "Z" + new Date().getTime();
            Thread.sleep(1);
            Document traceabilityCodeDoc = new Document("traceabilityCode", value + "?traceabilityCode=" + traceabilityCode)
                    .append("_traceabilityCodeId", traceabilityCodeId)
                    .append("enableStatus", false)
                    .append("billNo", billNo)
                    .append("createUserId", userId)
                    .append("createUserName", userName);
            traceabilityCodeList.add(traceabilityCodeDoc);
        }

        traceabilityCodeDetailDao.insertMany(traceabilityCodeList);

    }

    @Override
    public VtuzxMap getTraceabilityCodeList(VtuzxToken token, Map<String, Object> param) {
        Criteria cond = new Criteria();
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");

        VtuzxPage page = traceabilityCodeDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("codeCount", VtuzxUtil.getInt(doc, "codeCount"))
                .append("enabledCount", VtuzxUtil.getInt(doc, "enabledCount"))
                .append("noEnabledCount", VtuzxUtil.getInt(doc, "noEnabledCount"))
                .append("createUserId", VtuzxUtil.getString(doc, "createUserId"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxMap getTraceabilityCodeDetail(VtuzxToken token, Map<String, Object> param) {
        String id = VtuzxUtil.getObject(param, "id");

        Document traceabilityCodeDoc = traceabilityCodeDao.findById(id);
        VtuzxMap header = new VtuzxMap(traceabilityCodeDoc);
        Date createTime = VtuzxUtil.getObject(header, "createTime");
        header.remove("createTime");
        header.append("createTime", VtuzxUtil.formatYmdHmsF(createTime));

        List<VtuzxMap> dataList = new ArrayList<>();
        Iterator<Document> detailItr = traceabilityCodeDetailDao.findList(Criteria.where("_traceabilityCodeId").is(FastUtil.convertId(id)), null, 0, 0);
        while (detailItr.hasNext()) {
            Document detailDoc = detailItr.next();
            VtuzxMap detailMap = new VtuzxMap(detailDoc);
            detailMap.append("id", VtuzxUtil.removeString(detailMap, "_id"));
            detailMap.append("traceabilityCodeId", VtuzxUtil.removeString(detailMap, "_traceabilityCodeId"));
            dataList.add(detailMap);
        }
        return new VtuzxMap(IVtuzxConst.Key_data, dataList).append("header", header);
    }

    @Override
    public void deleteTraceabilityCode(VtuzxToken token, Map<String, Object> param) {
        List<String> ids = VtuzxUtil.getObject(param, "ids");
        for (String id: ids) {
            ObjectId _id = FastUtil.convertId(id);
            traceabilityCodeDao.deleteMany(Criteria.where("_id").is(_id));
            traceabilityCodeDetailDao.deleteMany(Criteria.where("_traceabilityCodeId").is(_id));
        }
    }

    @Override
    public void updateMaterial(VtuzxToken token, Map<String, Object> param) {
        String id = VtuzxUtil.getObject(param, "id");
        String prdStandardNo = VtuzxUtil.getObject(param, "prdStandardNo");
        String prdLicence = VtuzxUtil.getObject(param, "prdLicence");
        String seaAreaLocation = VtuzxUtil.getObject(param, "seaAreaLocation");
        materialDao.updateById(id, new Document("prdStandardNo",prdStandardNo).append("prdLicence", prdLicence).append("seaAreaLocation", seaAreaLocation));
    }

    @Override
    public VtuzxMap saveGetMaterialByKey(VtuzxToken token, String key, int pageSize, int pageIndex) {
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(key)) {
            cond.orOperator(Criteria.where("fNumber").regex("^" + key + ".*$", "i"), Criteria.where("fName").regex("^.*" + key + ".*$"));
        }
        VtuzxPage page = materialDao.page(cond, new Document("fNumber", 1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc ->
                new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                        .append("materialName", VtuzxUtil.getString(doc, "fName"))
                        .append("materialNo", VtuzxUtil.getString(doc, "fNumber"))
                        .append("materialModel", VtuzxUtil.getString(doc, "fSpecification"))
                        .append("unitName", VtuzxUtil.getString(doc, "fBaseUnitIdFName")));

        return new VtuzxMap(IVtuzxConst.Key_data, dataList);
    }

    /**
     * 下载物料列表
     * @param token
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public VtuzxDownloadBean downloadMaterial(VtuzxToken token, Map<String, Object> param) throws Exception {
        String fName = VtuzxUtil.getString(param, "fName");
        String fNumber = VtuzxUtil.getString(param, "fNumber");
        String fMATERIALID = VtuzxUtil.getString(param, "fMATERIALID");
        String fCreateOrgName = VtuzxUtil.getString(param, "fCreateOrgName");
        String fMaterialGroupName = VtuzxUtil.getString(param, "fMaterialGroupName");
        String fTaxRateName = VtuzxUtil.getString(param, "fTaxRateName");
        String fSpecification = VtuzxUtil.getString(param, "fSpecification");
        String goodsType = VtuzxUtil.getString(param, "goodsType");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(fName)) {
            cond.and("fName").regex(fName);
        }
        if (!VtuzxUtil.isEmpty(fNumber)) {
            cond.and("fNumber").regex("^" + fNumber + ".*$");
        }
        if (!VtuzxUtil.isEmpty(fMATERIALID)) {
            cond.and("fMATERIALID").regex(fMATERIALID);
        }
        if (!VtuzxUtil.isEmpty(fCreateOrgName)) {
            cond.and("fCreateOrgName").regex(fCreateOrgName);
        }
        if (!VtuzxUtil.isEmpty(goodsType)) {
            cond.and("goodsType").regex(goodsType);
        }
        if (!VtuzxUtil.isEmpty(fMaterialGroupName)) {
            cond.and("fMaterialGroupName").regex(fMaterialGroupName);
        }
        if (!VtuzxUtil.isEmpty(fTaxRateName)) {
            cond.and("fTaxRateName").regex(fTaxRateName);
        }
        if (!VtuzxUtil.isEmpty(fSpecification)) {
            cond.and("fSpecification").regex(fSpecification);
        }

        VtuzxPage page = materialDao.page(cond, new Document("fNumber", 1), 0, 0);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("fMATERIALID", VtuzxUtil.getString(doc, "fMATERIALID"))
                .append("fCreateOrgNumber", VtuzxUtil.getString(doc, "fCreateOrgNumber"))
                .append("fCreateOrgName", VtuzxUtil.getString(doc, "fCreateOrgName"))
                .append("fName", VtuzxUtil.getString(doc, "fName"))
                .append("fNumber", VtuzxUtil.getString(doc, "fNumber"))
                .append("fSpecification", VtuzxUtil.getString(doc, "fSpecification"))
                .append("fMaterialGroupNumber", VtuzxUtil.getString(doc, "fMaterialGroupNumber"))
                .append("fMaterialGroupName", VtuzxUtil.getString(doc, "fMaterialGroupName"))
                .append("fTaxRateNumber", VtuzxUtil.getString(doc, "fTaxRateNumber"))
                .append("fTaxRateName", VtuzxUtil.getString(doc, "fTaxRateName"))
                .append("fDocumentStatus", VtuzxUtil.getString(doc, "fDocumentStatus"))
                .append("fErpClsID", VtuzxUtil.getString(doc, "fErpClsID"))
                .append("fBaseUnitIdFName", VtuzxUtil.getString(doc, "fBaseUnitIdFName"))
                .append("fBaseUnitIdNumber", VtuzxUtil.getString(doc, "fBaseUnitIdNumber"))
                .append("prdStandardNo", VtuzxUtil.getString(doc, "prdStandardNo"))
                .append("prdLicence", VtuzxUtil.getString(doc, "prdLicence"))
                .append("goodsType", VtuzxUtil.getString(doc, "goodsType"))
                .append("seaAreaLocation", VtuzxUtil.getString(doc, "seaAreaLocation"))
                .append("fCreateDate", VtuzxUtil.getString(doc, "fCreateDate").substring(0, 10)));
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "物料列表");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "物料内码"),
                new VtuzxExcelCell(col++, "物料编码"),
                new VtuzxExcelCell(col++, "物料名称"),
                new VtuzxExcelCell(col++, "物料规格"),
                new VtuzxExcelCell(col++, "单位"),
                new VtuzxExcelCell(col++, "物料分组"),
                new VtuzxExcelCell(col++, "创建日期")
        ));
        sheet0.addRow(header0);

        for (VtuzxMap detail : dataList) {
            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fMATERIALID")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fNumber")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fSpecification")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fBaseUnitIdFName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fMaterialGroupName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "fCreateDate"))
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 300},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 150},
                new int[]{7, 150}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("物料列表" + timestamp + ".xlsx", stream);
    }

    @Override
    public void restoreSupplier(VtuzxToken token, String fNumber) {
        supplierDao.updateManyRedirect(Criteria.where("fNumber").is(fNumber),
                new Document("$set",new Document("isDelete",false)));
    }

    @Override
    public VtuzxDownloadBean downloadTrayList(VtuzxToken token, Map<String, Object> param) throws Exception {
        String trayNumber = VtuzxUtil.getString(param, "trayNumber");
        String trayName = VtuzxUtil.getString(param, "trayName");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        Criteria cond = new Criteria();
        if (!VtuzxUtil.isEmpty(trayNumber)) {
            cond.and("trayNumber").regex(trayNumber);
        }
        if (!VtuzxUtil.isEmpty(trayName)) {
            cond.and("trayName").regex(trayName);
        }
        if (!VtuzxUtil.isEmpty(createUserName)) {
            cond.and("createUserName").regex(createUserName);
        }

        VtuzxPage page = trayDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("trayNumber", VtuzxUtil.getString(doc, "trayNumber"))
                .append("rfid", VtuzxUtil.getObject(doc, "rfid"))
                .append("remark", VtuzxUtil.getString(doc, "remark"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("highlight",VtuzxUtil.getString(doc,"highlight"))
                .append("trayName", VtuzxUtil.getString(doc, "trayName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime"))));
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "托盘");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "托盘编号"),
                new VtuzxExcelCell(col++, "托盘名称"),
                new VtuzxExcelCell(col++, "rfid"),
                new VtuzxExcelCell(col++, "创建人员"),
                new VtuzxExcelCell(col++, "创建时间"),
                new VtuzxExcelCell(col, "电量状态")
        ));
        sheet0.addRow(header0);

        for (VtuzxMap detail : dataList) {

            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "trayNumber")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "trayName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "rfid")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createUserName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "createTime")),
                    new VtuzxExcelCell(col, VtuzxUtil.getString(detail, "highlight").equals("connect") ? "未连接" : VtuzxUtil.getString(detail, "highlight").equals("hight") ? "高电量" : "低电量")
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 300},
                new int[]{4, 200},
                new int[]{5, 200}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("托盘" + timestamp + ".xlsx", stream);
    }
}
